package com.panopset.centralen.resource;

import static com.panopset.Util.generateStackHashKey;
import static com.panopset.Util.isPopulated;

import java.util.Properties;

import com.panopset.Base64;

/**
 *
 * Name value pair persistent container.
 *
 * @author Karl Dinwiddie
 *
 */
public abstract class PersistentContainer {

    /**
     * Value supplier.
     */
    private ValueMirror valueMirror;

    /**
     * Default value.
     */
    private final String defaultValue;

    /**
     * Name value pair value.
     */
    private String value;

    /**
     * Name value pair key.
     */
    private final String key;

    /**
     * Create value mirror, for example a text field.
     *
     * @return Value mirror.
     */
    protected abstract ValueMirror createValueMirror();

    /**
     * Persistent container validation.
     *
     * @param valueToCheck
     *            Value to check.
     * @return true if value is valid.
     */
    protected abstract boolean isValid(String valueToCheck);

    /**
     * Constructor.
     *
     * @param initialValue
     *            Initial, or default value.
     */
    public PersistentContainer(final String initialValue) {
        key = generateStackHashKey();
        if (initialValue != null) {
            defaultValue = initialValue;
        } else {
            defaultValue = "";
        }
    }

    /**
     * Get value mirror.
     *
     * @return Value mirror.
     */
    private ValueMirror getValueMirror() {
        if (valueMirror == null) {
            valueMirror = createValueMirror();
        }
        return valueMirror;
    }

    /**
     * Get value.
     *
     * @return Name value pair value.
     */
    public final String getValue() {
        value = getValueMirror().getValue();
        if (!isPopulated(value)) {
            setValue(defaultValue);
        }
        return value;
    }

    /**
     * Set value.
     *
     * @param newValue
     *            Name value pair value to set.
     */
    public final void setValue(final String newValue) {
        if (!isValid(newValue)) {
            return;
        }
        value = newValue;
        getValueMirror().setValue(value);
    }

    /**
     * @return Name value pair default value.
     */
    public final String getDefaultValue() {
        return defaultValue;
    }

    /**
     * @return Name value pair key.
     */
    public final String getKey() {
        return key;
    }

    /**
     * Override to take action after loading.
     */
    protected void load() {

    }


    /**
     * Load value from storage.
     *
     * @param properties
     *            Properties to load value from.
     */
    final void loadProperties(final Properties properties) {
        String s = properties.getProperty(this.key);
        if (isPopulated(s)) {
            setValue(new String(Base64.decode(s)));
        } else {
            setValue(getDefaultValue());
        }
        load();
    }

    /**
     * Persist value to storage.
     *
     * @param properties
     *            Properties to persist value to.
     */
    final void flushProperties(final Properties properties) {
        if (getValue() != null) {
            properties.put(getKey(), Base64.encode(getValue()));
        }
    }

    /**
     * PersistentContainer value mirror.  Usually a text field or other
     * gui component that will mirror values.
     */
    public interface ValueMirror {

        /**
         * Set value.
         *
         * @param newValue
         *            Set new value for mirror.
         */
        void setValue(String newValue);

        /**
         * Get value.
         *
         * @return Name value pair value.
         */
        String getValue();
    }
}
